package com.sun.designpatternsdemo.singleton.bean

/**
 * 版权：xx公司 版权所有
 * @author sun
 * 版本：1.0
 * 创建日期：2021/6/29 13:58
 * 描述：单列模式的懒汉式
 *
 */
class SingletonLanHan {
    companion object {

        /**
         * 3.单例模式的懒汉式[线程不安全，不可用]
         */
        private var singletonLanHan: SingletonLanHan? = null

        fun getInstance(): SingletonLanHan? {
            if (singletonLanHan == null) { // 这里线程是不安全的,可能得到两个不同的实例
                singletonLanHan = SingletonLanHan()
            }
            return singletonLanHan
        }

        /**
         * 4. 懒汉式线程安全的:[线程安全，效率低不推荐使用]
         *
         *
         * 缺点：效率太低了，每个线程在想获得类的实例时候，执行getInstance()方法都要进行同步。
         * 而其实这个方法只执行一次实例化代码就够了，
         * 后面的想获得该类实例，直接return就行了。方法进行同步效率太低要改进。
         */
        private var singletonLanHanTwo: SingletonLanHan? = null

        @Synchronized
        fun getSingletonLanHanTwo(): SingletonLanHan? {
            if (singletonLanHanTwo == null) { // 这里线程是不安全的,可能得到两个不同的实例
                singletonLanHanTwo = SingletonLanHan()
            }
            return singletonLanHanTwo
        }

        /**
         * 5. 单例模式懒汉式[线程不安全，不可用]
         *
         *
         * 虽然加了锁，但是等到第一个线程执行完instance=new Singleton()跳出这个锁时，
         * 另一个进入if语句的线程同样会实例化另外一个Singleton对象，线程不安全的原理跟3类似。
         */
        private var instanceThree: SingletonLanHan? = null

        fun getSingletonLanHanThree(): SingletonLanHan? {
            if (instanceThree == null) {
                synchronized(SingletonLanHan::class.java) { // 线程不安全
                    instanceThree = SingletonLanHan()
                }
            }
            return instanceThree
        }

        /**
         * 6.单例模式懒汉式双重校验锁[推荐用]
         * 懒汉式变种,属于懒汉式的最好写法,保证了:延迟加载和线程安全
         */
        private var singletonLanHanFour: SingletonLanHan? = null

        fun getSingletonLanHanFour(): SingletonLanHan? {
            if (singletonLanHanFour == null) {
                synchronized(SingletonLanHan::class.java) {
                    if (singletonLanHanFour == null) {
                        singletonLanHanFour = SingletonLanHan()
                    }
                }
            }
            return singletonLanHanFour
        }
    }
}